`include "DEFWIDTH.v"
/* verilator lint_off UNUSEDSIGNAL */
module EXE_STAGE(
    input clk,
    input reset,
    //allowin
    input mem_allowin,
    output exe_allowin,
    //from id
    input id_to_exe_valid,
    input [`ID_TO_EXE_BUS_WD -1:0] id_to_exe_bus,
	//to id
	output [`EXE_TO_ID_BRBUS_WD -1:0] exe_to_id_brbus,
    //to mem
    output exe_to_mem_valid,
    output [`EXE_TO_MEM_BUS_WD -1:0] exe_to_mem_bus,
	//from mem
	input [`MEM_TO_EXE_BRBUS_WD -1:0] mem_to_exe_brbus,

    //for inst_store
    output data_sram_en,
    output data_sram_wen,
    output [31:0] data_sram_addr,
    output [31:0] data_sram_wdata,
    output [ 3:0] data_sram_wmask,
	input  [31:0] data_sram_rdata,

    //bypass
    output [`EXE_TO_ID_BYPASS_WD -1:0] exe_to_id_bypass,
    output [4:0] exe_to_id_rdbypass,
    output       exe_to_id_rfwenbypass,
    output [`EXE_TO_ID_CFBYPASS_WD -1:0] exe_to_id_cfbypass,
    output [11:0] exe_to_id_csrbypass,
    output       exe_to_id_cfwenbypass,
	
	output		 exe_to_if_loadbypass,
	output		 exe_to_id_loadbypass,
	output		 exe_to_id_brjmpbypass,
	input		 mem_to_exe_brjmpbypass
);
reg exe_valid;
wire exe_ready_go,exe_flush;
reg [`ID_TO_EXE_BUS_WD -1:0] id_to_exe_bus_r;//接受id到exe的bus的内容

//EXE1,输入
wire [31:0] alu_src1,alu_src2,alu_result;
wire        dst_load,dst_store,dst_writeback,dst_writeback_csr;
wire [ 3:0] ls_op;
wire [ 4:0] rd;
wire [31:0] rs2,rs1,imm;
wire [10:0] alu_op;
wire		exe_branch_bge,exe_branch_blt;
wire [31:0] exe_pc,exe_dnpc,exe_inst,exe_tvec;
wire        exe_ebreak,exe_ecall;

assign exe_ready_go = 1'b1;
assign exe_allowin = !exe_valid || (exe_ready_go && mem_allowin);//无阻塞
assign exe_flush = mem_to_exe_brjmpbypass;
always @(posedge clk) begin
    if(reset) begin
        exe_valid <= 1'b0;
    end else if(exe_allowin) begin
        exe_valid <= id_to_exe_valid;
    end

    if(id_to_exe_valid && exe_allowin) begin 
        id_to_exe_bus_r <= id_to_exe_bus;
    end else begin
		id_to_exe_bus_r[251] <= 1'b0;
	end 
end

assign {
    alu_src1,
    alu_src2,
    dst_store,
    dst_load,
    dst_writeback,
	dst_writeback_csr,
    ls_op,
	rs1,
    rs2,
    rd,
    alu_op,
	imm,
	exe_branch_bge,
	exe_branch_blt,
    exe_pc,
	exe_dnpc,
	exe_inst,
    exe_ebreak,
	exe_ecall,
	exe_tvec
} = exe_flush ? 'b0 : id_to_exe_bus_r;


//EXE2,执行
alu exe_alu(
    .alu_src1(alu_src1),
    .alu_src2(alu_src2),
    .alu_op(alu_op),
    .alu_result(alu_result)
);



//EXE3,store指令
//将RF[rs2]存到MEM[ RF[rs1]+imm ]中
//alu_result = RF[rs1]+imm
assign data_sram_en = dst_load | dst_store;
assign data_sram_wen = dst_store & exe_valid;
assign data_sram_addr = alu_result;//注意，load和store都用这个addr（因为load和store不会同时发生）
assign data_sram_wdata = rs2;
assign data_sram_wmask = ls_op;

//EXE4,输出
assign exe_to_mem_valid = exe_valid && exe_ready_go;
assign exe_to_mem_bus = {
    dst_load, //1
	dst_writeback, //1
	dst_writeback_csr,
	exe_inst, //32
    ls_op, //4
    alu_result, //32
	imm[11:0], //12，用于csrrw、csrrs、csrrc
    rs1,//32
	rd, //5
    exe_pc, //32
	exe_dnpc, //32
	exe_ebreak, //1
	exe_ecall,
	exe_tvec //32
};
assign exe_to_id_bypass = alu_result ;//debug
assign exe_to_id_rdbypass = rd;
assign exe_to_id_rfwenbypass = ~dst_load & dst_writeback;
assign exe_to_id_cfbypass = rs1;
assign exe_to_id_csrbypass = imm[11:0];
assign exe_to_id_cfwenbypass = dst_writeback_csr;

assign exe_to_if_loadbypass = dst_load & exe_valid;
assign exe_to_id_loadbypass = dst_load & exe_valid;

assign exe_to_id_brjmpbypass = mem_to_exe_brjmpbypass 
							 | (( (exe_branch_bge & ~alu_result[0]) 
								| (exe_branch_blt & alu_result[0]) 
								)& exe_valid);
assign exe_to_id_brbus = mem_to_exe_brjmpbypass ? mem_to_exe_brbus : exe_pc + imm;
						 //exe_ecall				? exe_tvec		   : exe_pc + imm;

endmodule
